# -*- coding:utf-8 -*-
"""
-------------------------------------------------
   File Name:      parser.py
   Author:         luzhongfu
   date:           2020/05/16
-------------------------------------------------
"""
from decimal import Decimal
from typing import Any
import re
import datetime
import calendar
from handler.reader import ExcelReader
from utils import common
from utils import logs

V_Types = ['string', 'number', 'date']


class MappingRuleParser:
    def __init__(self, reader: ExcelReader) -> None:
        self.reader = reader
        self.pattern = '{.*?}'
        self.extra_values = {}
        self.time_values = self._build_times()
        self.index_values = {}
        self.log = logs.LogHandler(__name__)

    def parse_field_value(self,
                          field: str,
                          source_row: int,
                          field_type='string'):
        rule = {
            'expr': field,
            'type': field_type,
        }
        return self.parse('default', rule, source_row)

    def _fix_type(self):
        if self.result is None:
            return
        if self.type == 'number' and type(self.result) == str:
            self.result = Decimal(self.result)

    def get_index(self):
        field = f'{self.filename}:{self.title}'
        value = self.index_values.get(field)
        if value is None:
            value = 0
        else:
            value += 1
        self.index_values[field] = value
        return value

    def parse(self, filename: str, rule: dict, source_row: int) -> Any:
        self._check_rule(rule)
        self.expr = rule.get('expr')
        self.type = rule.get('type') or 'string'
        self.title = rule.get('title') or 'default_title'
        self.filename = filename
        self.result = self.expr
        self._parse(source_row)

        self._fix_type()
        return self.result

    def parse_extra_value(self, key: str, source_row: int):
        condition = self.extra_values.get(key)
        if condition is None:
            return None

        from_field = condition['from_field']
        eq_field = condition['eq_field']
        select_field = condition['select_field']

        # hack
        # print('eq_field', eq_field)
        if self.extra_values.get(eq_field):
            eq_value = self.parse_extra_value(eq_field, source_row)
        else:
            eq_value = self.reader.get_field_value(eq_field, source_row)
        columns = self.reader.get_field_columns(from_field)

        # print('eq_value: ', eq_value)

        index = 0
        row_num = 1  # 实际是从第二列开始比较
        for column_value in columns:
            row_num += 1
            if column_value == eq_value:
                index = row_num
                break
        if index == 0:
            # print('columns: ', columns)
            # print('eq_value: ', eq_value)
            raise ValueError(
                f'未找到 {from_field}:{eq_field} 匹配项; {eq_field} 值为: {eq_value}')
        return self.reader.get_field_value(select_field, index)

    def parse_condition_to_fields(self, condition: dict):
        where = condition.get('where')
        select = condition.get('select')
        if where is None or select is None:
            raise ValueError('缺少参数项 where 或 select')
        wheres = where.split('==')
        if len(wheres) != 2:
            raise ValueError('where 必须被 "==" 分割为两份')
        from_field = common.field_strip(wheres[0])
        eq_field = common.field_strip(wheres[1])
        select_field = common.field_strip(select)

        return from_field, eq_field, select_field

    def add_extra_value(self, key: str, condition: dict):
        try:
            from_field, eq_field, select_field = self.parse_condition_to_fields(
                condition)
        except ValueError as e:
            raise ValueError(f'{key} {e}')

        self.extra_values[key] = {
            'from_field': from_field,
            'eq_field': eq_field,
            'select_field': select_field
        }

    def _build_times(self):
        year = datetime.date.today().year
        month = datetime.date.today().month
        day = datetime.date.today().day
        _, monthCountDay = calendar.monthrange(year, month)
        return {
            'year': str(year),
            'month': str(month).zfill(2),
            'day': str(day).zfill(2),
            'monthLastDay': str(monthCountDay).zfill(2)
        }

    def _parse(self, source_row):
        expr_type = type(self.expr)
        if expr_type == int or expr_type == float:
            return
        if expr_type == str and '{' not in self.expr:
            return

        if expr_type != str:
            raise ValueError('不支持解析表达式类型: %s' % expr_type)

        self.result = self._replace_data(self.expr, source_row)

    def _get_field(self, expr):
        searchObj = re.search(self.pattern, expr)
        if searchObj is None:
            return
        match = searchObj.group()
        field = common.field_strip(match)
        return field

    def _replace_data(self, expr, row):
        key = self._get_field(expr)
        if key is None:
            return expr
        value = None
        if key == 'index':
            value = self.get_index()
        if value is None:
            value = self.time_values.get(key)
        if value is None:
            value = self.parse_extra_value(key, row)
        if value is None:
            value = self.reader.get_field_value(key, row)
        if value is None:
            raise ValueError('找不到对应匹配的值: %s' % key)
        old_expr = expr
        expr = re.sub(self.pattern, str(value), old_expr, count=1)  # 只替换第一个
        self.log.debug(f'sub: {old_expr}  ->  {expr}')
        return self._replace_data(expr, row)

    def _check_rule(self, rule):
        t = rule.get('type')
        if not t:
            raise ValueError('没有定义类型')
        if t not in V_Types:
            raise ValueError('不支持解析类型: %s' % t)

        expr = rule.get('expr')
        if expr is None:
            raise ValueError('没有定义表达式')

    def _check_dict_expr(self, dict_expr):
        expr = dict_expr.get('expr')
        key = dict_expr.get('key')
        where = dict_expr.get('where')
        select = dict_expr.get('select')
        base_err = '表达式参数不够, 缺少:'
        err = base_err
        if expr is None:
            err += ' expr'
        if key is None:
            err == ' key'
        if where is None:
            err == ' where'
        if select is None:
            err == ' select'

        if err != base_err:
            raise ValueError(err)


if __name__ == "__main__":
    from openpyxl import Workbook
    reader = ExcelReader()
    parser = MappingRuleParser(reader)

    wb = Workbook()
    new_sheet = wb.active
    title = 'AA'
    value = 1
    new_sheet.cell(row=1, column=1).value = title
    new_sheet.cell(row=2, column=1).value = value

    filename = 'add_mem_file'
    reader.add_mem_file(filename, new_sheet)

    # parser = MappingRuleParser(reader)
    parse_value = parser.parse_field_value('{add_mem_file.AA}', 2)
    # print('parse_value = ', parse_value)

    # wb = Workbook()
    # sheet = wb.active
    # value = '123'
    # sheet.cell(row=1, column=1).value = value

    # read = sheet.cell(row=1, column=1).value

    # print('read: ', read)
